home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / pgp20src.zip / KEYMAINT.C < prev    next >
C/C++ Source or Header  |  1992-09-01  |  28KB  |  1,082 lines

  1. /*    keymaint.c  - Keyring maintenance pass routines for PGP.
  2.     PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
  3.  
  4.     (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
  5.     The author assumes no liability for damages resulting from the use
  6.     of this software, even if the damage results from defects in this
  7.     software.  No warranty is expressed or implied.
  8.  
  9.     All the source code Philip Zimmermann wrote for PGP is available for
  10.     free under the "Copyleft" General Public License from the Free
  11.     Software Foundation.  A copy of that license agreement is included in
  12.     the source release package of PGP.  Code developed by others for PGP
  13.     is also freely available.  Other code that has been incorporated into
  14.     PGP from other sources was either originally published in the public
  15.     domain or was used with permission from the various authors.  See the
  16.     PGP User's Guide for more complete information about licensing,
  17.     patent restrictions on certain algorithms, trademarks, copyrights,
  18.     and export controls.  
  19.  
  20.     keymaint.c implemented by Branko Lankester.
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <time.h>
  25. #include "mpilib.h"
  26. #include "random.h"
  27. #include "crypto.h"
  28. #include "fileio.h"
  29. #include "keymgmt.h"
  30. #include "mpiio.h"
  31. #include "language.h"
  32. #include "pgp.h"
  33.  
  34.  
  35. void setup_trust();
  36. int maint_pass1(FILE *f);
  37. int maint_trace_chain(FILE *f);
  38. int maint_cmpfiles(FILE *f, FILE *g);
  39. int trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth);
  40. int check_secretkey(FILE *f, long keypos);
  41. int set_legit(FILE *f, long trustpos, int trust_count);
  42. long lookup_by_keyID(FILE *f, byte *srch_keyID);
  43. void show_userid(FILE *f, byte *keyID);
  44. int show_trust(byte, byte);
  45. int show_legit(byte, byte);
  46. void write_trust_pos(FILE *f, byte keyctrl, long pos);
  47.  
  48. /* returned when trying to do a maintenance pass on a secret keyring or keyfile */
  49. #define    ERR_NOTRUST        -7
  50.  
  51. #define TRUST_MASK        7    /* mask for userid/signature trust bytes */
  52. #define SET_TRUST(b,v)    (*(b) = (*(b) & ~TRUST_MASK) | (v))
  53. #define TRUST_LEV(b)    ((b) & TRUST_MASK)
  54.  
  55. #define    TRUST_FAC(x)    (trust_tbl[TRUST_LEV(x)])
  56.  
  57. /*
  58.  * table for tuning user paranoia index.
  59.  * values represent contribution of one signature indexed by the
  60.  * SIGTRUST of a signature
  61.  */
  62. int trust_tbl[8];
  63.  
  64. static int marginal_min;
  65. static int complete_min;    /* total count needed for a fully legit key */
  66.  
  67. int marg_min = 2;        /* number of marginally trusted signatures needed for
  68.                            a fully legit key (can be set in config.pgp). */
  69. int compl_min = 1;        /* number of fully trusted signatures needed */
  70.  
  71. char trust_lst[8][16] = {
  72.     "undefined",        /* PSTR("undefined") */
  73.     "unknown",            /* PSTR("unknown") */
  74.     "untrusted",        /* PSTR("untrusted") */
  75.     "<3>",                /* unused */
  76.     "<4>",                /* unused */
  77.     "marginal",            /* PSTR("marginal") */
  78.     "complete",            /* PSTR("complete") */
  79.     "ultimate",            /* PSTR("ultimate") */
  80. };
  81.  
  82. char legit_lst[4][16] = {
  83.     "undefined",
  84.     "untrusted",
  85.     "marginal",
  86.     "complete"
  87. };
  88.  
  89. int trustlst_len = 9;    /* length of longest trust word */
  90. int legitlst_len = 9;    /* length of longest legit word */
  91.  
  92. char floppyring[MAX_PATH] = "";
  93. int max_cert_depth = 4;        /* maximum nesting of signatures */
  94.  
  95. static boolean check_only = FALSE;
  96. static boolean mverbose;
  97. static FILE *sec_fp;
  98. static FILE *floppy_fp = NULL;
  99. static int undefined_trust;    /* number of legit keys with undef. trust */
  100.   
  101. int
  102. maintenance(char *ringfile, int options)
  103. {
  104.     FILE *f, *g;
  105.     int status;
  106.     char *tmpring;
  107.     char secretkeyring[MAX_PATH];
  108.  
  109.     check_only = (options & MAINT_CHECK) != 0;
  110.     mverbose = (options & MAINT_VERBOSE) != 0;
  111.     undefined_trust = 0;
  112.  
  113.     if ((tmpring = tempfile(TMP_TMPDIR)) == NULL)
  114.         return(-1);
  115.     if ((g = fopenbin(tmpring, "w+")) == NULL)
  116.         return(-1);
  117.  
  118.     if ((f = fopenbin(ringfile,"r")) == NULL)
  119.     {    fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
  120.         fclose(g);
  121.         return(-1);
  122.     }
  123.  
  124.     buildfilename(secretkeyring, SECRET_KEYRING_FILENAME);
  125.     if ((sec_fp = fopenbin(secretkeyring, "r")) == NULL)
  126.         fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
  127.                 secretkeyring);
  128.  
  129.     if (!(options & MAINT_SILENT) && *floppyring != '\0' &&
  130.         (floppy_fp = fopenbin(floppyring, "r")) == NULL)
  131.         fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"),
  132.                 floppyring);
  133.  
  134.     if ((status = copyfile(f, g, -1L)) < 0)
  135.     {    fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ringfile);
  136.         goto failed;
  137.     }
  138.  
  139.     setup_trust();
  140.     if (mverbose)
  141.         fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n"));
  142.     rewind(g);
  143.     if ((status = maint_pass1(g)) < 0)
  144.         goto failed;
  145.  
  146.     if (mverbose)
  147.         fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n"));
  148.     rewind(g);
  149.     if ((status = maint_trace_chain(g)) < 0)
  150.         goto failed;
  151.  
  152.     if (!(options & MAINT_SILENT))
  153.     {    if (mverbose)
  154.             fprintf(pgpout, PSTR("\nPass 3: Comparing with original keyring...\n"));
  155.         rewind(f);
  156.         rewind(g);
  157.         if ((status = maint_cmpfiles(f, g)) < 0)
  158.             goto failed;
  159.     } else
  160.         status = 1;
  161.  
  162.     fflush(g);
  163.     if (ferror(g))
  164.     {    status = -1;
  165.         goto failed;
  166.     }
  167.     fclose(f);
  168.     fclose(g);
  169.     if (sec_fp)
  170.         fclose(sec_fp);
  171.     if (floppy_fp)
  172.     {    fclose(floppy_fp);
  173.         floppy_fp = NULL;
  174.     }
  175.  
  176. #ifdef DEBUG
  177.     if (check_only)
  178.     {
  179.         if (undefined_trust)
  180.             fprintf(pgpout, "\nKeyring contains %d fully validated key(s) with undefined trust.\n", undefined_trust);
  181.         else
  182.             if (status == 0)
  183.                 fprintf(pgpout, "\nMaintenance check OK.\n");
  184.         rmtemp(tmpring);
  185.         return(0);
  186.     }
  187. #endif
  188.  
  189.     if (status > 0)        /* keyring is changed */
  190.     {
  191.         if (options & MAINT_SILENT)
  192.         {    /* implicit maintenance pass (after pgp -ka, -kr, -ks) */
  193.             remove(ringfile);
  194.             if (savetemp(tmpring, ringfile) == NULL)
  195.                 return(-1);
  196.         }
  197.         else
  198.         {    /* explicit maintenance pass */
  199.             fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile);
  200.             if (!getyesno('y'))
  201.             {
  202.                 rmtemp(tmpring);
  203.                 return(0);
  204.             }
  205.             if (savetempbak(tmpring, ringfile))
  206.                 return(-1);
  207.         }
  208.     }
  209.     else
  210.         rmtemp(tmpring);
  211.  
  212.     return(0);
  213.  
  214. failed:
  215.     if (sec_fp)
  216.         fclose(sec_fp);
  217.     if (floppy_fp)
  218.     {    fclose(floppy_fp);
  219.         floppy_fp = NULL;
  220.     }
  221.     fclose(f);
  222.     fclose(g);
  223. #ifdef DEBUG
  224.     savetempbak(tmpring, "tmpring.pub");
  225. #else
  226.     rmtemp(tmpring);
  227. #endif
  228.     return(status);
  229. }
  230.  
  231.  
  232. /*
  233.  * check if axiomatic keys are present in the secret keyring and
  234.  * clear userid and signature trust bytes
  235.  */
  236. int
  237. maint_pass1(FILE *f)
  238. {
  239.     int status;
  240.     char userid[256];
  241.     byte keyID[KEYFRAGSIZE];
  242.     byte ctb;
  243.     byte keyctrl;
  244.     boolean buckstop = FALSE, show_user = FALSE;
  245.     boolean compromised = FALSE;
  246.     int buckstopcount = 0;
  247.     int usercount = 0;
  248.     long keypos = 0;
  249.  
  250.     while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
  251.     {
  252.         if (status < 0)
  253.             return(status);
  254.  
  255.         if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
  256.             continue;
  257.         if (compromised && is_ctb_type(ctb, CTB_SKE_TYPE) && !usercount)
  258.             continue;    /* compromise certificate */
  259.  
  260.         /* other packets should have trust byte */
  261.         if (read_trust(f, &keyctrl) < 0)
  262.             return(ERR_NOTRUST);        /* not a public keyring */
  263.  
  264.         if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
  265.         {
  266.             if (compromised = is_compromised(f))
  267.                 keyctrl = KC_OWNERTRUST_NEVER;
  268.             if ((keyctrl & KC_BUCKSTOP))
  269.             {
  270.                 if (check_secretkey(f, keypos) == 0)
  271.                 {
  272.                     ++buckstopcount;
  273.                     buckstop = TRUE;
  274.                     if (mverbose)
  275.                         fprintf(pgpout, "* %s",keyIDstring(keyID));
  276.                 }
  277.                 else
  278.                 {    /* not in secret keyring */
  279.                     keyctrl &= ~KC_BUCKSTOP;
  280.                     if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE)
  281.                         keyctrl = KC_OWNERTRUST_ALWAYS;
  282.                     if (mverbose)
  283.                         fprintf(pgpout, ". %s",keyIDstring(keyID));
  284.                 }
  285.                 show_user = mverbose;
  286.             }
  287.             else
  288.             {
  289.                 buckstop = FALSE;
  290.                 show_user = FALSE;
  291.             }
  292.             usercount = 0;
  293.             keyctrl &= ~KC_VISITED;
  294.  
  295.         }
  296.         else if (ctb == CTB_USERID)
  297.         {
  298.             if (show_user)
  299.             {
  300.                 if (usercount)        /* more than one user ID */
  301.                     fprintf(pgpout, "        ");
  302.                 fprintf(pgpout, "  %s\n", EXTERNAL(userid));
  303.             }
  304.               if (buckstop)
  305.                   keyctrl = KC_LEGIT_COMPLETE;
  306.               else
  307.                   keyctrl = KC_LEGIT_UNKNOWN;
  308.             ++usercount;
  309.         }
  310.         else if (is_ctb_type(ctb, CTB_SKE_TYPE))
  311.         {
  312.             keyctrl = KC_SIGTRUST_UNDEFINED;
  313.         }
  314.         fseek(f, -1L, SEEK_CUR);
  315.         fwrite(&keyctrl, 1, 1, f);
  316.         fseek(f, 0L, SEEK_CUR);
  317.         keypos = ftell(f);
  318.     }
  319.     if (buckstopcount == 0 && mverbose)
  320.     {
  321.         fprintf(pgpout, PSTR("No ultimately-trusted keys.\n"));
  322.     }
  323.     return(0);
  324. }
  325.  
  326.  
  327. /*
  328.  * scan keyring for buckstop keys and start the recursive trace_sig_chain()
  329.  * on them
  330.  */
  331. int
  332. maint_trace_chain(FILE *f)
  333. {
  334.     int status;
  335.     char userid[256];
  336.     byte keyID[KEYFRAGSIZE];
  337.     long trustpos = 0;
  338.     byte ctb;
  339.     byte own_trust;
  340.     boolean buckstop = FALSE;
  341.  
  342.     while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
  343.     {
  344.         if (status < 0)
  345.             return status;
  346.  
  347.         if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
  348.         {
  349.             trustpos = ftell(f);
  350.             if ((status = read_trust(f, &own_trust)) < 0)
  351.                 return(status);
  352.             buckstop = (own_trust & KC_BUCKSTOP) != 0;
  353.             userid[0] = '\0';
  354.         }
  355.         else if (ctb == CTB_USERID)
  356.         {
  357.             if (buckstop)
  358.             {
  359.                 buckstop = FALSE;    /* only for first user id */
  360.                 if (mverbose)
  361.                     fprintf(pgpout, "* %s\n", EXTERNAL(userid));
  362.  
  363.                 if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
  364.                 {    SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
  365.                     write_trust_pos(f, own_trust, trustpos);
  366.                 }
  367.                 if (trace_sig_chain(f, keyID, TRUST_LEV(own_trust), 0) < 0)
  368.                     return(-1);
  369.             }
  370.         }
  371.     }
  372.     return(0);
  373. }
  374.  
  375.  
  376. /* 
  377.  * check if the maintenance pass changed anything
  378.  * returns 0 if files f and g are equal.
  379.  */
  380. int
  381. maint_cmpfiles(FILE *f, FILE *g)
  382. {
  383.     int status;
  384.     char userid[256];
  385.     byte keyID[KEYFRAGSIZE];
  386.     byte sigkeyID[KEYFRAGSIZE];
  387.     byte ctb;
  388.     byte kc_orig, kc_new;
  389.     int usercount = 0;
  390.     int changed = 0;
  391.  
  392.     fprintf(pgpout, PSTR("  KeyID   Trust      Validity  User ID\n"));
  393.     while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) == 0)
  394.     {
  395.         if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
  396.             continue;
  397.         /* other packets should have trust byte */
  398.  
  399.         fseek(g, ftell(f), SEEK_SET);
  400.         if (read_trust(f, &kc_orig) < 0 || read_trust(g, &kc_new) < 0)
  401.         {    status = ERR_NOTRUST;
  402.             break;
  403.         }
  404.  
  405.         if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
  406.         {
  407.             if (is_compromised(f))
  408.             {
  409.                 fprintf(pgpout, "# ");
  410.                 nextkeypacket(f, &ctb);    /* skip compromise certificate */
  411.                 nextkeypacket(g, &ctb);
  412.             }
  413.             else if ((kc_new & KC_BUCKSTOP))
  414.                 fprintf(pgpout, "* ");
  415.             else
  416.                 fprintf(pgpout, "  ");
  417.  
  418.             fprintf(pgpout, "%s ",keyIDstring(keyID));
  419.             changed += show_trust(kc_new, kc_orig);
  420.             usercount = 0;
  421.             userid[0] = '\0';
  422.         }
  423.         else if (ctb == CTB_USERID)
  424.         {
  425.               if (usercount)        /* more than one user ID */
  426.                 fprintf(pgpout, "          %*s", trustlst_len, "");
  427.               ++usercount;
  428.             changed += show_legit(kc_new, kc_orig);
  429.             fprintf(pgpout, "%s\n", EXTERNAL(userid));
  430.         }
  431.         else if (is_ctb_type(ctb, CTB_SKE_TYPE))
  432.         {
  433.             if (kc_new & KC_CONTIG)
  434.                 fprintf(pgpout, "c        ");
  435.             else
  436.                 fprintf(pgpout, "         ");
  437.             changed += show_trust(kc_new, kc_orig);
  438.             fprintf(pgpout, "  %*s", legitlst_len, "");
  439.             show_userid(f, sigkeyID);
  440.         }
  441.     }
  442.     if (status >= -1 && changed)
  443.         fprintf(pgpout, PSTR("\n%d \"trust byte(s)\" changed.\n"), changed);
  444.     if (status < -1)    /* -1 is OK, EOF */
  445.         return(status);
  446.     return(changed);
  447. }
  448.  
  449.  
  450. void
  451. init_trust_lst()
  452. {
  453.     static int initialized = 0;
  454.     int i, len;
  455.     char *s;
  456.  
  457.     if (initialized)
  458.         return;
  459.     for (i = 0; i < 8; ++i)
  460.     {    if (trust_lst[i][0])
  461.         {    s = PSTR (trust_lst[i]);
  462.             if (s != trust_lst[i])
  463.                 strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1);
  464.             len = strlen(s);
  465.             if (len > trustlst_len)
  466.                 trustlst_len = len;
  467.         }
  468.     }
  469.     for (i = 0; i < 4; ++i)
  470.     {    s = PSTR (legit_lst[i]);
  471.         if (s != legit_lst[i])
  472.             strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1);
  473.         len = strlen(s);
  474.         if (len > legitlst_len)
  475.             legitlst_len = len;
  476.     }
  477.     ++trustlst_len;
  478.     ++legitlst_len;
  479.     initialized = 1;
  480. }
  481.  
  482. int
  483. show_trust(byte kc_new, byte kc_orig)
  484. {
  485. #ifdef DEBUG
  486.     fprintf(pgpout, " %02x", kc_new);
  487.     if (kc_new != kc_orig)
  488.     {
  489.         fprintf(pgpout, " (%02x)    ", kc_orig);
  490.         return(1);
  491.     }
  492.     fprintf(pgpout, "        ");
  493.     return(0);
  494. #else
  495.     init_trust_lst();
  496.     fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
  497.             trustlst_len, trust_lst[TRUST_LEV(kc_new)]);
  498.     return(kc_new != kc_orig);
  499. #endif
  500. }
  501.  
  502. int
  503. show_legit(byte kc_new, byte kc_orig)
  504. {
  505. #ifdef DEBUG
  506.     return(show_trust(kc_new, kc_orig));
  507. #else
  508.     init_trust_lst();
  509.     kc_new &= KC_LEGIT_MASK;
  510.     kc_orig &= KC_LEGIT_MASK;
  511.     fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
  512.             legitlst_len, legit_lst[kc_new]);
  513.     return(kc_new != kc_orig);
  514. #endif
  515. }
  516.  
  517.  
  518. /*
  519.  * Find all signatures made with a key, fromID is the keyID of this key
  520.  * owner_trust is the trust level of this key.
  521.  * If a trusted signature makes a key fully legit then signatures made
  522.  * with this key are also recursively traced on down the tree.
  523.  */
  524. int
  525. trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth)
  526. {
  527.     long filepos;
  528.     int status;
  529.     int trust_count = 0;
  530.     byte keyID[KEYFRAGSIZE];
  531.     byte sigkeyID[KEYFRAGSIZE];
  532.     byte ctb;
  533.     byte own_trust, sig_trust;
  534.     char userid[256];
  535.     int sig_count = 0;
  536.     int compromised = 0;
  537.     long usertrustpos = 0;
  538.     long ownt_pos = 0;
  539.  
  540.     if (max_cert_depth > 8)
  541.         max_cert_depth = 8;
  542.     if (depth > max_cert_depth)
  543.         return(0);
  544.     filepos = ftell(f);
  545.     rewind(f);
  546.     userid[0] = '\0';
  547.     while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1)
  548.     {
  549.         if (status < 0)
  550.             return status;
  551.  
  552.         if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
  553.         {
  554.             compromised = is_compromised(f);
  555.             ownt_pos = ftell(f);
  556.             if (read_trust(f, &own_trust))
  557.                 return(ERR_NOTRUST);
  558.             userid[0] = '\0';
  559.         }
  560.         else if (ctb == CTB_USERID)
  561.         {
  562.             usertrustpos = ftell(f);
  563.             trust_count = 0;
  564.         }
  565.         else if (is_ctb_type(ctb, CTB_SKE_TYPE))
  566.         {
  567.             if (compromised)
  568.                 continue;
  569.             read_trust(f, &sig_trust);
  570.             if (memcmp(sigkeyID, fromID, sizeof(sigkeyID)) == 0)
  571.             {
  572.                 ++sig_count;
  573.                 if (mverbose)
  574.                     fprintf(pgpout, "%*s  > %s\n", 2*depth, "", EXTERNAL(userid));
  575.                 if (TRUST_LEV(sig_trust) != owner_trust)
  576.                 {
  577.                     SET_TRUST(&sig_trust, owner_trust);
  578.                 }
  579.                 sig_trust |= KC_CONTIG;
  580.                 fseek(f, -1L, SEEK_CUR);
  581.                 fwrite(&sig_trust, 1, 1, f);
  582.                 fseek(f, 0L, SEEK_CUR);
  583.             }
  584.  
  585.             if (sig_trust & KC_CONTIG)
  586.             {
  587.                 trust_count += TRUST_FAC(sig_trust);
  588.  
  589.                 switch (set_legit(f, usertrustpos, trust_count))
  590.                 {
  591.                     case -1: return(-1);
  592.                     case  1:
  593.                         if ((own_trust & (KC_BUCKSTOP|KC_VISITED)) == 0)
  594.                         {
  595.                             if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
  596.                                 SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
  597.                             own_trust |= KC_VISITED;
  598.                             write_trust_pos(f, own_trust, ownt_pos);
  599.                             trace_sig_chain(f, keyID, TRUST_LEV(own_trust), depth+1);
  600.                         }
  601.                 }
  602.             }
  603.         }
  604.     }
  605.     if (mverbose && sig_count == 0)    /* no signatures from this user */
  606.         fprintf(pgpout, PSTR("%*s  (No signatures)\n"), 2*depth, "");
  607.     fseek(f, filepos, SEEK_SET);
  608.     return(0);
  609. }
  610.  
  611.  
  612. int
  613. check_secretkey(FILE *f, long keypos)
  614. {
  615.     int status = -1;
  616.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  617.     unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION];
  618.     char userid[256];
  619.     byte keyID[KEYFRAGSIZE];
  620.     long savepos, pktlen;
  621.     byte ctb;
  622.  
  623.     if (sec_fp == NULL)
  624.         return(-1);
  625.  
  626.     savepos = ftell(f);
  627.     fseek(f, keypos, SEEK_SET);
  628.     if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e,
  629.                     NULL, NULL, NULL, NULL, NULL, NULL) < 0)
  630.         goto ex;
  631.     extract_keyID(keyID, n);
  632.  
  633.     do    /* get userid */
  634.     {    if (readkpacket(f, &ctb, userid, NULL, NULL) < 0)
  635.             goto ex;
  636.     } while (ctb != CTB_USERID);
  637.  
  638.     if (lookup_by_keyID(sec_fp, keyID) < 0)
  639.     {
  640. #if 0
  641.         if (!check_only)
  642.         {
  643.             fprintf(pgpout, PSTR (
  644. "\nAn \"axiomatic\" key is one which does not need certifying by\n\
  645. anyone else.  Usually this special status is reserved only for your\n\
  646. own keys, which should also appear on your secret keyring.  The owner\n\
  647. of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\
  648. by you to certify any or all other keys.\n"));
  649.             fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\
  650. is designated as an \"ultimately-trusted\" introducer, but the key\n\
  651. does not appear in the secret keyring.\n\
  652. Use this key as an ultimately-trusted introducer (y/N)? "), EXTERNAL(userid));
  653.             status = (getyesno('n') ? 0 : 1);
  654.         }
  655. #else
  656.         status = 1;
  657. #endif
  658.     }
  659.     else
  660.     {
  661.         long kpos = ftell(sec_fp);
  662.         if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec,
  663.                         NULL, NULL, NULL, NULL, NULL, NULL) < 0)
  664.         {
  665.             fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n"));
  666.             goto ex;
  667.         }
  668.         if (mp_compare(n, nsec) || mp_compare(e, esec))
  669.         {    /* Red Alert! */
  670.             fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\
  671. does not match the corresponding key in the secret keyring.\n"), EXTERNAL(userid));
  672.             fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
  673.             status = -2;
  674.         }
  675.         else
  676.             status = 0;
  677.  
  678.         if (floppy_fp)
  679.         {
  680.             if (lookup_by_keyID(floppy_fp, keyID) < 0)
  681.             {
  682.                 fprintf(pgpout, PSTR("Public key for: \"%s\"\n\
  683. is not present in the backup keyring '%s'.\n"),
  684.                         EXTERNAL(userid), floppyring);
  685.             }
  686.             else
  687.             {
  688.                 pktlen = ftell(sec_fp) - kpos;
  689.                 fseek(sec_fp, kpos, SEEK_SET);
  690.                 while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ;
  691.                 if (pktlen != -1)
  692.                 {
  693.                     fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\
  694. does not match the key in the backup keyring '%s'.\n"),
  695.                             EXTERNAL(userid), floppyring);
  696.                     fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
  697.                     status = -2;
  698.                 }
  699.             }
  700.         }
  701.     }
  702. ex:
  703.     fseek(f, savepos, SEEK_SET);
  704.     return(status);
  705. }
  706.  
  707.  
  708. void
  709. setup_trust()
  710. {    /* initialize trust table */
  711.     if (marg_min == 0)    /* marginally trusted signatures are ignored */
  712.     {
  713.         trust_tbl[5] = 0;
  714.         trust_tbl[6] = 1;
  715.         complete_min = compl_min;
  716.     }
  717.     else
  718.     {
  719.         if (marg_min < compl_min)
  720.             marg_min = compl_min;
  721.         trust_tbl[5] = compl_min;
  722.         trust_tbl[6] = marg_min;
  723.         complete_min = compl_min * marg_min;
  724.     }
  725.     trust_tbl[7] = complete_min;    /* ultimate trust */
  726.     marginal_min = complete_min / 2;
  727. }
  728.  
  729.  
  730. /*
  731.  * set legit level of a userid
  732.  * returns 1 if the key/userid pair is fully legit.
  733.  */
  734. int
  735. set_legit(FILE *f, long trustpos, int trust_count)
  736. {
  737.     long filepos;
  738.     byte keyctrl;
  739.  
  740.     filepos = ftell(f);
  741.     fseek(f, trustpos, SEEK_SET);    /* user id trust byte */
  742.     if (read_trust(f, &keyctrl) < 0)
  743.         return(-1);
  744.     
  745.     if (trust_count < marginal_min)
  746.         keyctrl = KC_LEGIT_UNTRUSTED;
  747.     else if (trust_count < complete_min)
  748.         keyctrl = KC_LEGIT_MARGINAL;
  749.     else
  750.         keyctrl = KC_LEGIT_COMPLETE;
  751.     
  752.     fseek(f, trustpos, SEEK_SET);
  753.     write_trust(f, keyctrl);
  754.  
  755.     fseek(f, filepos, SEEK_SET);
  756.  
  757.     if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE)
  758.         return(1);
  759.     else
  760.         return(0);
  761. }
  762.  
  763.  
  764. int ask_owntrust(char *userid, byte cur_trust)
  765. /* Ask for a wetware decision from the human on how much to trust 
  766. this key's owner to certify other keys.  Returns trust value. */
  767. {
  768.     char buf[8];
  769.  
  770.     if (check_only)
  771.     {    ++undefined_trust;
  772.         return(KC_OWNERTRUST_UNDEFINED);
  773.     }
  774.  
  775.     fprintf(pgpout, 
  776. PSTR("\nMake a determination in your own mind whether this key actually\n\
  777. belongs to the person whom you think it belongs to, based on available\n\
  778. evidence.  If you think it does, then based on your estimate of\n\
  779. that person's integrity and competence in key management, answer\n\
  780. the following question:\n"));  
  781.     fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\
  782. to act as an introducer and certify other people's public keys to you?\n\
  783. (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "), EXTERNAL(userid));
  784.     fflush(pgpout);
  785.     getstring(buf, sizeof(buf)-1, TRUE);
  786.     switch (buf[0])
  787.     {    case '1': return KC_OWNERTRUST_UNKNOWN;
  788.         case '2': return KC_OWNERTRUST_NEVER;
  789.         case '3': return KC_OWNERTRUST_USUALLY;
  790.         case '4': return KC_OWNERTRUST_ALWAYS;
  791.         default: return(TRUST_LEV(cur_trust));
  792.     }
  793. }    /* ask_owntrust */
  794.  
  795.  
  796. /* 
  797.  * compare all key packets in keyring file f with file g
  798.  * XXX: untested
  799.  */
  800. int
  801. keyring_cmp(FILE *f, FILE *g)
  802. {
  803.     int status, error = 0, badkeys = 0;
  804.     byte ctb;
  805.     byte keyID[KEYFRAGSIZE];
  806.     char userid[256];
  807.     long pktlen, keypos = 0;
  808.  
  809.     rewind(f);
  810.     while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) == 0)
  811.     {
  812.         if (is_key_ctb(ctb))
  813.         {
  814.             pktlen = ftell(f) - keypos;
  815.             fseek(f, keypos, SEEK_SET);
  816.             if (lookup_by_keyID(g, keyID) < 0)
  817.             {
  818.                 error = 1;
  819.                 continue;
  820.             }
  821.             while (--pktlen >= 0 && getc(f) == getc(g)) ;
  822.             if (pktlen != -1)
  823.             {
  824.                 error = 2;
  825.                 ++badkeys;
  826.             }
  827.  
  828.         }
  829.         if (error && ctb == CTB_USERID)
  830.         {
  831.             switch (error) {
  832.                 case 1: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
  833. is not present in backup keyring\n"), EXTERNAL(userid));
  834.                 case 2: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
  835. does not match key in backup keyring\n"), EXTERNAL(userid));
  836.             }
  837.             error = 0;
  838.         }
  839.         keypos = ftell(f);
  840.     }
  841.     if (error)
  842.         status = -5;
  843.     return(status < 0 ? status : badkeys);
  844. }
  845.  
  846.  
  847. int
  848. readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID)
  849. {
  850.     int status;
  851.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  852.  
  853.     status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e,
  854.                     NULL, NULL, NULL, NULL, sigkeyID, NULL);
  855.  
  856.     if (status < 0)
  857.     {
  858. #ifdef DEBUG
  859.         if (status < -1)
  860.             fprintf(stderr, "readkeypacket returned %d\n", status);
  861. #endif
  862.         return(status);
  863.     }
  864.  
  865.     if (keyID && is_key_ctb(*ctb))
  866.         extract_keyID(keyID, n);
  867.  
  868.     if (userid && *ctb == CTB_USERID)
  869.         PascalToC(userid);
  870.  
  871.     return(0);
  872. }
  873.  
  874. long
  875. lookup_by_keyID(FILE *f, byte *srch_keyID)
  876. {
  877.     int status;
  878.     long keypos = 0;
  879.     byte keyID[KEYFRAGSIZE];
  880.     byte ctb;
  881.  
  882.     rewind(f);
  883.     while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) == 0)
  884.     {
  885.         if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
  886.         {
  887.             fseek(f, keypos, SEEK_SET);
  888.             return(keypos);
  889.         }
  890.         keypos = ftell(f);
  891.     }
  892.     return(status);
  893. }
  894.  
  895.  
  896. void
  897. show_userid(FILE *f, byte *keyID)
  898. {
  899.     long filepos;
  900.     char userid[256];
  901.     byte ctb;
  902.  
  903.     filepos = ftell(f);
  904.     if (lookup_by_keyID(f, keyID) >= 0)
  905.         while (readkpacket(f, &ctb, userid, NULL, NULL) == 0)
  906.             if (ctb == CTB_USERID)
  907.             {
  908.                 fprintf(pgpout, "%s\n", EXTERNAL(userid));
  909.                 fseek(f, filepos, SEEK_SET);
  910.                 return;
  911.             }
  912.  
  913.     fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID));
  914.     fseek(f, filepos, SEEK_SET);
  915. }
  916.  
  917. /*
  918.  * show the key in file f at file position keypos.
  919.  * 'what' controls the info that will be shown:
  920.  *   SHOW_TRUST: show trust byte info
  921.  *   SHOW_SIGS:  show signatures
  922.  * these constants can be or'ed to get both
  923.  */
  924. int
  925. show_key(FILE *f, long keypos, int what)
  926. {
  927.     int status;
  928.     long filepos;
  929.     char userid[256];
  930.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  931.     byte sigkeyID[KEYFRAGSIZE];
  932.     word32 timestamp;
  933.     byte ctb, keyctrl;
  934.     int userids = 0;
  935.     boolean print_trust = FALSE;
  936.     int precision = global_precision;
  937.  
  938.     filepos = ftell(f);
  939.     fseek(f, keypos, SEEK_SET);
  940.     while ((status = readkeypacket(f, FALSE, &ctb, (byte *)×tamp, userid,
  941.                     n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) == 0)
  942.     {
  943.         if (is_key_ctb(ctb))
  944.         {    if (userids)
  945.                 break;
  946.         }
  947.         else if (ctb == CTB_KEYCTRL)  /* trust bytes only in public keyrings */
  948.         {
  949.             if (what & SHOW_TRUST)
  950.                 print_trust = TRUE;
  951.         }
  952.         else if (ctb == CTB_USERID)
  953.         {    if (userids == 0)
  954.             {    PascalToC(userid);    /* for display */
  955.                 fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),EXTERNAL(userid));
  956.                 fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"),
  957.                     countbits(n), key2IDstring(n), cdate(×tamp) );
  958.                 if (print_trust)
  959.                 {
  960.                     switch (TRUST_LEV(keyctrl))
  961.                     {
  962.                         case KC_OWNERTRUST_UNDEFINED:
  963.                         case KC_OWNERTRUST_UNKNOWN:
  964.                             /* Just don't say anything in this case */
  965.                             break;
  966.                         case KC_OWNERTRUST_NEVER:     /* untrusted */
  967.                             fprintf(pgpout, PSTR("This user is untrusted to certify other keys.\n"));
  968.                             break;
  969.                         case KC_OWNERTRUST_USUALLY:     /* marginal trust */
  970.                             fprintf(pgpout, PSTR("This user is generally trusted to certify other keys.\n"));
  971.                             break;
  972.                         case KC_OWNERTRUST_ALWAYS:     /* complete trust */
  973.                             fprintf(pgpout, PSTR("This user is completely trusted to certify other keys.\n"));
  974.                             break;
  975.                         case KC_OWNERTRUST_ULTIMATE:     /* axiomatic, ultimate trust */
  976.                             fprintf(pgpout, PSTR("This axiomatic key is ultimately trusted to certify other keys.\n"));
  977.                             break;
  978.                         default:
  979.                             break;
  980.                     }    /* switch */
  981.                 }
  982.                 ++userids;
  983.             }
  984.             else
  985.             {    PascalToC(userid);
  986.                 if (what != 0)
  987.                     fprintf(pgpout, "\n");
  988.                 fprintf(pgpout,PSTR("Also known as: %s\n"), EXTERNAL(userid));
  989.             }
  990.             if (print_trust)
  991.             {
  992.                 read_trust(f, &keyctrl);
  993.                 switch (keyctrl & KC_LEGIT_MASK)
  994.                 {
  995.                     case 0:     /* undefined certification level */
  996.                     case 1:     /* uncertified */
  997.                         fprintf(pgpout, PSTR("This key/userID association is not certified.\n"));
  998.                         break;
  999.                     case 2:     /* marginal certification */
  1000.                         fprintf(pgpout, PSTR("This key/userID association is marginally certified.\n"));
  1001.                         break;
  1002.                     case 3:     /* complete certification */
  1003.                         fprintf(pgpout, PSTR("This key/userID association is fully certified.\n"));
  1004.                         break;
  1005.                     default:    /* can't get here, right? */
  1006.                         break;
  1007.                 }    /* switch */
  1008.             }    /* print_trust */
  1009.         }
  1010.         else if ((what & SHOW_SIGS) && is_ctb_type(ctb, CTB_SKE_TYPE))
  1011.         {
  1012.             if (print_trust)
  1013.             {
  1014.                 read_trust(f, &keyctrl);
  1015.                 switch (TRUST_LEV(keyctrl))
  1016.                 {
  1017.                     case KC_SIGTRUST_UNDEFINED:     /* undefined trust level */
  1018.                     case KC_SIGTRUST_UNKNOWN:
  1019.                         /* Just don't say anything in this case */
  1020.                         fprintf(pgpout, PSTR("  Questionable certification from:\n  "));
  1021.                         break;
  1022.                     case KC_SIGTRUST_UNTRUSTED:     /* untrusted */
  1023.                         fprintf(pgpout, PSTR("  Untrusted certification from:\n  "));
  1024.                         break;
  1025.                     case KC_SIGTRUST_MARGINAL:     /* marginal trust */
  1026.                         fprintf(pgpout, PSTR("  Generally trusted certification from:\n  "));
  1027.                         break;
  1028.                     case KC_SIGTRUST_COMPLETE:     /* complete trust */
  1029.                         fprintf(pgpout, PSTR("  Completely trusted certification from:\n  "));
  1030.                         break;
  1031.                     case KC_SIGTRUST_ULTIMATE:     /* axiomatic, ultimate trust */
  1032.                         fprintf(pgpout, PSTR("  Axiomatically trusted certification from:\n  "));
  1033.                         break;
  1034.                     default:    /* can't get here, right? */
  1035.                         break;
  1036.                 }    /* switch */
  1037.             }
  1038.             else
  1039.                 fprintf(pgpout, PSTR("  Certified by: "));
  1040.             show_userid(f, sigkeyID);
  1041.         }
  1042.     }
  1043.     if (status == -1 && userids)
  1044.         status = 0;
  1045.     set_precision(precision);
  1046.     fseek(f, filepos, SEEK_SET);
  1047.     return(status);
  1048. }
  1049.  
  1050.  
  1051. void
  1052. write_trust_pos(FILE *f, byte keyctrl, long pos)
  1053. {
  1054.     long fpos;
  1055.  
  1056.     fpos = ftell(f);
  1057.     fseek(f, pos, SEEK_SET);
  1058.     write_trust(f, keyctrl);
  1059.     fseek(f, fpos, SEEK_SET);
  1060. }
  1061.  
  1062. int
  1063. read_trust(FILE *f, byte *keyctrl)
  1064. {
  1065.     unsigned char buf[3];
  1066.  
  1067.     if (fread(buf, 1, 3, f) != 3)
  1068.         return -1;
  1069.     if (buf[0] != CTB_KEYCTRL)
  1070.     {
  1071.         if (is_ctb(buf[0]))
  1072.             return(ERR_NOTRUST);
  1073.          else
  1074.             return(-3);        /* bad data */
  1075.     }
  1076.     if (buf[1] != 1)        /* length must be 1 */
  1077.         return(-3);
  1078.     if (keyctrl)
  1079.         *keyctrl = buf[2];
  1080.     return(0);
  1081. }
  1082.